using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Collections;
using Dracham.GUI.Helpers;

namespace Dracham.GUI.Controls
{
    public class Textbox : Control
    {
        private Texture2D texture;
        private String text = "";
        private SpriteFont font;
        private float charLength;

        private readonly Int32 paddingLeft = 2;
        private readonly Int32 paddingRight = 10;

        private Keys? lastPressedKey;
        private readonly Double writeDelay = 300;
        private Double timeSinceLastKeyPress = 0;
        private readonly Double cursorDelay = 500;
        private Double timeSinceLastCursorDisplay = 0;
        private Boolean showCursor = false;

        #region properties

        public String Text
        {
            get { return text; }
            set { text = value; }
        }

        #endregion

        #region events 

        public delegate void ReturnKeyPressHandler();
        public event ReturnKeyPressHandler ReturnKeyPress;

        private void OnReturnKeyPress()
        {
            if (ReturnKeyPress != null)
            {
                ReturnKeyPress();
            }
        }

        #endregion

        public Textbox(String name, Vector2 location, String fontName)
        {
            this.Name = name;
            this.Location = location;
            this.Size = new System.Drawing.Size(248, 19);
            this.texture = GUIHelper.Content.Load<Texture2D>("gui\\textbox");
            this.font = GUIHelper.Content.Load<SpriteFont>("fonts\\" + fontName);
            this.charLength = this.font.MeasureString("h").X;
        }

        public void Render(GameTime gameTime, SpriteBatch batch)
        {
            Int32 start = 0;
            float width = this.charLength * this.text.Length;
            if (width > this.Size.Width - this.paddingRight)
            {
                start = (Int32)((width - ((float)this.Size.Width - this.paddingRight)) / this.charLength);
                width = (this.text.Length - start) * this.charLength;
            }

            batch.Draw(texture, new Rectangle((Int32)Location.X, (Int32)Location.Y, Size.Width, Size.Height), Color.White);
            batch.DrawString(this.font, text.Substring(start), new Vector2(Location.X + this.paddingLeft, Location.Y + 2), Color.Black);

            //
            // cursor
            if (showCursor && this.Focused)
            {
                batch.DrawString(this.font, "|", new Vector2(Location.X + width, (float)Location.Y), Color.Black);
                batch.DrawString(this.font, "|", new Vector2(Location.X + width, (float)Location.Y + 3), Color.Black);
            }

            if (timeSinceLastCursorDisplay > cursorDelay)
            {
                showCursor = showCursor ? false : true;
                timeSinceLastCursorDisplay = 0;
            }
            else
            {
                timeSinceLastCursorDisplay += gameTime.ElapsedGameTime.TotalMilliseconds;
            }
        }


        public override void Update(GameTime gt, Microsoft.Xna.Framework.Input.MouseState ms, Microsoft.Xna.Framework.Input.KeyboardState ks)
        {
            Keys[] keys = ks.GetPressedKeys();
            Boolean keyIsOk = false;
            TextboxKeyboardKey tkk = null;
            if (keys.Length > 0)
            {
                Keys cKey = keys[keys.Length - 1];
                if (lastPressedKey.HasValue)
                {
                    if (lastPressedKey == cKey && timeSinceLastKeyPress > 0)
                    {
                        if (timeSinceLastKeyPress < writeDelay)
                        {
                            timeSinceLastKeyPress += gt.ElapsedGameTime.TotalMilliseconds;
                            return;
                        }
                        else
                        {
                            timeSinceLastKeyPress = 0;
                        }
                    }
                }

                String key = cKey.ToString().ToLower();

                if (key == "")
                    return;

                if (key.Length == 1 && char.IsLetterOrDigit(key[0]))
                {
                    text += key;
                    keyIsOk = true;
                }
                else if ((tkk = GUIHelper.TextboxKeyboard.GetKey(key,
                     ks.IsKeyDown(Keys.LeftShift) || ks.IsKeyDown(Keys.RightShift),
                     ks.IsKeyDown(Keys.LeftControl) || ks.IsKeyDown(Keys.RightControl),
                     ks.IsKeyDown(Keys.LeftAlt) || ks.IsKeyDown(Keys.RightAlt))) != null)
                {
                    text += tkk.Text;
                    keyIsOk = true;
                }
                else
                {
                    HandleSpecialKey(cKey);
                    keyIsOk = true;
                }

                if (keyIsOk)
                {
                    if (lastPressedKey != cKey)
                        timeSinceLastKeyPress = 1;
                }

                lastPressedKey = cKey;
            }
            else { lastPressedKey = null; }

            if (ks.IsKeyDown(Keys.Enter))
            {
                OnReturnKeyPress();
            }
        }

        private void HandleSpecialKey(Keys key)
        {
            if (key == Keys.Back && text.Length > 0)
            {
                text = text.Remove(text.Length - 1);
            }
        }
    }
}
